home *** CD-ROM | disk | FTP | other *** search
/ PCGUIA 2010 Software/Programs / PCGuia_programas.iso / Software / Utils / The GIMP / gimp-2.6.8-i686-setup.exe / {app} / lib / gimp / 2.0 / plug-ins / pyconsole.py < prev    next >
Encoding:
Python Source  |  2009-12-15  |  20.5 KB  |  666 lines

  1. #
  2. #   pyconsole.py
  3. #
  4. #   Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
  5. #   Portions of code by Geoffrey French.
  6. #
  7. #   This program is free software; you can redistribute it and/or modify
  8. #   it under the terms of the GNU Lesser General Public version 2.1 as
  9. #   published by the Free Software Foundation.
  10. #
  11. #   See COPYING.lib file that comes with this distribution for full text
  12. #   of the license.
  13. #
  14.  
  15. # This module 'runs' python interpreter in a TextView widget.
  16. # The main class is Console, usage is:
  17. # Console(locals=None, banner=None, completer=None, use_rlcompleter=True, start_script='') -
  18. # it creates the widget and 'starts' interactive session; see the end
  19. # of this file. If start_script is not empty, it pastes it as it was
  20. # entered from keyboard.
  21. #
  22. # Console has "command" signal which is emitted when code is about to
  23. # be executed. You may connect to it using console.connect or
  24. # console.connect_after to get your callback ran before or after the
  25. # code is executed.
  26. #
  27. # To modify output appearance, set attributes of console.stdout_tag and
  28. # console.stderr_tag.
  29. #
  30. # Console may subclass a type other than gtk.TextView, to allow syntax
  31. # highlighting and stuff,
  32. # e.g.:
  33. #   console_type = pyconsole.ConsoleType(moo.edit.TextView)
  34. #   console = console_type(use_rlcompleter=False, start_script="import moo\nimport gtk\n")
  35. #
  36. # This widget is not a replacement for real terminal with python running
  37. # inside: GtkTextView is not a terminal.
  38. # The use case is: you have a python program, you create this widget,
  39. # and inspect your program interiors.
  40.  
  41. import gtk
  42. import gtk.gdk as gdk
  43. import gobject
  44. import pango
  45. import gtk.keysyms as _keys
  46. import code
  47. import sys
  48. import keyword
  49. import re
  50.  
  51. # commonprefix() from posixpath
  52. def _commonprefix(m):
  53.     "Given a list of pathnames, returns the longest common leading component"
  54.     if not m: return ''
  55.     prefix = m[0]
  56.     for item in m:
  57.         for i in range(len(prefix)):
  58.             if prefix[:i+1] != item[:i+1]:
  59.                 prefix = prefix[:i]
  60.                 if i == 0:
  61.                     return ''
  62.                 break
  63.     return prefix
  64.  
  65. class _ReadLine(object):
  66.  
  67.     class Output(object):
  68.         def __init__(self, console, tag_name):
  69.             object.__init__(self)
  70.             self.buffer = console.get_buffer()
  71.             self.tag_name = tag_name
  72.         def write(self, text):
  73.             pos = self.buffer.get_iter_at_mark(self.buffer.get_insert())
  74.             self.buffer.insert_with_tags_by_name(pos, text, self.tag_name)
  75.  
  76.     class History(object):
  77.         def __init__(self):
  78.             object.__init__(self)
  79.             self.items = ['']
  80.             self.ptr = 0
  81.             self.edited = {}
  82.  
  83.         def commit(self, text):
  84.             if text and self.items[-1] != text:
  85.                 self.items.append(text)
  86.             self.ptr = 0
  87.             self.edited = {}
  88.  
  89.         def get(self, dir, text):
  90.             if len(self.items) == 1:
  91.                 return None
  92.  
  93.             if text != self.items[self.ptr]:
  94.                 self.edited[self.ptr] = text
  95.             elif self.edited.has_key(self.ptr):
  96.                 del self.edited[self.ptr]
  97.  
  98.             self.ptr = self.ptr + dir
  99.             if self.ptr >= len(self.items):
  100.                 self.ptr = 0
  101.             elif self.ptr < 0:
  102.                 self.ptr = len(self.items) - 1
  103.  
  104.             try:
  105.                 return self.edited[self.ptr]
  106.             except KeyError:
  107.                 return self.items[self.ptr]
  108.  
  109.     def __init__(self, quit_func=None):
  110.         object.__init__(self)
  111.  
  112.         self.quit_func = quit_func
  113.  
  114.         self.set_wrap_mode(gtk.WRAP_CHAR)
  115.         self.modify_font(pango.FontDescription("Monospace"))
  116.  
  117.         self.buffer = self.get_buffer()
  118.         self.buffer.connect("insert-text", self.on_buf_insert)
  119.         self.buffer.connect("delete-range", self.on_buf_delete)
  120.         self.buffer.connect("mark-set", self.on_buf_mark_set)
  121.         self.do_insert = False
  122.         self.do_delete = False
  123.  
  124.         self.stdout_tag = self.buffer.create_tag("stdout", foreground="#006000")
  125.         self.stderr_tag = self.buffer.create_tag("stderr", foreground="#B00000")
  126.         self._stdout = _ReadLine.Output(self, "stdout")
  127.         self._stderr = _ReadLine.Output(self, "stderr")
  128.  
  129.         self.cursor = self.buffer.create_mark("cursor",
  130.                                               self.buffer.get_start_iter(),
  131.                                               False)
  132.         insert = self.buffer.get_insert()
  133.         self.cursor.set_visible(True)
  134.         insert.set_visible(False)
  135.  
  136.         self.ps = ''
  137.         self.in_raw_input = False
  138.         self.run_on_raw_input = None
  139.         self.tab_pressed = 0
  140.         self.history = _ReadLine.History()
  141.         self.nonword_re = re.compile("[^\w\._]")
  142.  
  143.     def freeze_undo(self):
  144.         try: self.begin_not_undoable_action()
  145.         except: pass
  146.  
  147.     def thaw_undo(self):
  148.         try: self.end_not_undoable_action()
  149.         except: pass
  150.  
  151.     def raw_input(self, ps=None):
  152.         if ps:
  153.             self.ps = ps
  154.         else:
  155.             self.ps = ''
  156.  
  157.         iter = self.buffer.get_iter_at_mark(self.buffer.get_insert())
  158.  
  159.         if ps:
  160.             self.freeze_undo()
  161.             self.buffer.insert(iter, self.ps)
  162.             self.thaw_undo()
  163.  
  164.         self.__move_cursor_to(iter)
  165.         self.scroll_to_mark(self.cursor, 0.2)
  166.  
  167.         self.in_raw_input = True
  168.  
  169.         if self.run_on_raw_input:
  170.             run_now = self.run_on_raw_input
  171.             self.run_on_raw_input = None
  172.             self.buffer.insert_at_cursor(run_now + '\n')
  173.  
  174.     def on_buf_mark_set(self, buffer, iter, mark):
  175.         if mark is not buffer.get_insert():
  176.             return
  177.         start = self.__get_start()
  178.         end = self.__get_end()
  179.         if iter.compare(self.__get_start()) >= 0 and \
  180.            iter.compare(self.__get_end()) <= 0:
  181.                 buffer.move_mark_by_name("cursor", iter)
  182.                 self.scroll_to_mark(self.cursor, 0.2)
  183.  
  184.     def __insert(self, iter, text):
  185.         self.do_insert = True
  186.         self.buffer.insert(iter, text)
  187.         self.do_insert = False
  188.  
  189.     def on_buf_insert(self, buf, iter, text, len):
  190.         if not self.in_raw_input or self.do_insert or not len:
  191.             return
  192.         buf.stop_emission("insert-text")
  193.         lines = text.splitlines()
  194.         need_eol = False
  195.         for l in lines:
  196.             if need_eol:
  197.                 self._commit()
  198.                 iter = self.__get_cursor()
  199.             else:
  200.                 cursor = self.__get_cursor()
  201.                 if iter.compare(self.__get_start()) < 0:
  202.                     iter = cursor
  203.                 elif iter.compare(self.__get_end()) > 0:
  204.                     iter = cursor
  205.                 else:
  206.                     self.__move_cursor_to(iter)
  207.             need_eol = True
  208.             self.__insert(iter, l)
  209.         self.__move_cursor(0)
  210.  
  211.     def __delete(self, start, end):
  212.         self.do_delete = True
  213.         self.buffer.delete(start, end)
  214.         self.do_delete = False
  215.  
  216.     def on_buf_delete(self, buf, start, end):
  217.         if not self.in_raw_input or self.do_delete:
  218.             return
  219.  
  220.         buf.stop_emission("delete-range")
  221.  
  222.         start.order(end)
  223.         line_start = self.__get_start()
  224.         line_end = self.__get_end()
  225.  
  226.         if start.compare(line_end) > 0:
  227.             return
  228.         if end.compare(line_start) < 0:
  229.             return
  230.  
  231.         self.__move_cursor(0)
  232.  
  233.         if start.compare(line_start) < 0:
  234.             start = line_start
  235.         if end.compare(line_end) > 0:
  236.             end = line_end
  237.         self.__delete(start, end)
  238.  
  239.     def do_key_press_event(self, event, parent_type):
  240.         if not self.in_raw_input:
  241.             return parent_type.do_key_press_event(self, event)
  242.  
  243.         tab_pressed = self.tab_pressed
  244.         self.tab_pressed = 0
  245.         handled = True
  246.  
  247.         state = event.state & (gdk.SHIFT_MASK |
  248.                                 gdk.CONTROL_MASK |
  249.                                 gdk.MOD1_MASK)
  250.         keyval = event.keyval
  251.  
  252.         if not state:
  253.             if keyval == _keys.Return:
  254.                 self._commit()
  255.             elif keyval == _keys.Up:
  256.                 self.__history(-1)
  257.             elif keyval == _keys.Down:
  258.                 self.__history(1)
  259.             elif keyval == _keys.Left:
  260.                 self.__move_cursor(-1)
  261.             elif keyval == _keys.Right:
  262.                 self.__move_cursor(1)
  263.             elif keyval == _keys.Home:
  264.                 self.__move_cursor(-10000)
  265.             elif keyval == _keys.End:
  266.                 self.__move_cursor(10000)
  267.             elif keyval == _keys.Tab:
  268.                 cursor = self.__get_cursor()
  269.                 if cursor.starts_line():
  270.                     handled = False
  271.                 else:
  272.                     cursor.backward_char()
  273.                     if cursor.get_char().isspace():
  274.                         handled = False
  275.                     else:
  276.                         self.tab_pressed = tab_pressed + 1
  277.                         self.__complete()
  278.             else:
  279.                 handled = False
  280.         elif state == gdk.CONTROL_MASK:
  281.             if keyval == _keys.u:
  282.                 start = self.__get_start()
  283.                 end = self.__get_cursor()
  284.                 self.__delete(start, end)
  285.             elif keyval == _keys.d:
  286.                 if self.quit_func:
  287.                     self.quit_func()
  288.             else:
  289.                 handled = False
  290.         else:
  291.             handled = False
  292.  
  293.         if not handled:
  294.             return parent_type.do_key_press_event(self, event)
  295.         else:
  296.             return True
  297.  
  298.     def __history(self, dir):
  299.         text = self._get_line()
  300.         new_text = self.history.get(dir, text)
  301.         if not new_text is None:
  302.             self.__replace_line(new_text)
  303.         self.__move_cursor(0)
  304.         self.scroll_to_mark(self.cursor, 0.2)
  305.  
  306.     def __get_cursor(self):
  307.         return self.buffer.get_iter_at_mark(self.cursor)
  308.     def __get_start(self):
  309.         iter = self.__get_cursor()
  310.         iter.set_line_offset(len(self.ps))
  311.         return iter
  312.     def __get_end(self):
  313.         iter = self.__get_cursor()
  314.         if not iter.ends_line():
  315.             iter.forward_to_line_end()
  316.         return iter
  317.  
  318.     def __get_text(self, start, end):
  319.         return self.buffer.get_text(start, end, False)
  320.  
  321.     def __move_cursor_to(self, iter):
  322.         self.buffer.place_cursor(iter)
  323.         self.buffer.move_mark_by_name("cursor", iter)
  324.  
  325.     def __move_cursor(self, howmany):
  326.         iter = self.__get_cursor()
  327.         end = self.__get_cursor()
  328.         if not end.ends_line():
  329.             end.forward_to_line_end()
  330.         line_len = end.get_line_offset()
  331.         move_to = iter.get_line_offset() + howmany
  332.         move_to = min(max(move_to, len(self.ps)), line_len)
  333.         iter.set_line_offset(move_to)
  334.         self.__move_cursor_to(iter)
  335.  
  336.     def __delete_at_cursor(self, howmany):
  337.         iter = self.__get_cursor()
  338.         end = self.__get_cursor()
  339.         if not end.ends_line():
  340.             end.forward_to_line_end()
  341.         line_len = end.get_line_offset()
  342.         erase_to = iter.get_line_offset() + howmany
  343.         if erase_to > line_len:
  344.             erase_to = line_len
  345.         elif erase_to < len(self.ps):
  346.             erase_to = len(self.ps)
  347.         end.set_line_offset(erase_to)
  348.         self.__delete(iter, end)
  349.  
  350.     def __get_width(self):
  351.         if not (self.flags() & gtk.REALIZED):
  352.             return 80
  353.         layout = pango.Layout(self.get_pango_context())
  354.         letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  355.         layout.set_text(letters)
  356.         pix_width = layout.get_pixel_size()[0]
  357.         return self.allocation.width * len(letters) / pix_width
  358.  
  359.     def __print_completions(self, completions):
  360.         line_start = self.__get_text(self.__get_start(), self.__get_cursor())
  361.         line_end = self.__get_text(self.__get_cursor(), self.__get_end())
  362.         iter = self.buffer.get_end_iter()
  363.         self.__move_cursor_to(iter)
  364.         self.__insert(iter, "\n")
  365.  
  366.         width = max(self.__get_width(), 4)
  367.         max_width = max([len(s) for s in completions])
  368.         n_columns = max(int(width / (max_width + 1)), 1)
  369.         col_width = int(width / n_columns)
  370.         total = len(completions)
  371.         col_length = total / n_columns
  372.         if total % n_columns:
  373.             col_length = col_length + 1
  374.         col_length = max(col_length, 1)
  375.  
  376.         if col_length == 1:
  377.             n_columns = total
  378.             col_width = width / total
  379.  
  380.         for i in range(col_length):
  381.             for j in range(n_columns):
  382.                 ind = i + j*col_length
  383.                 if ind < total:
  384.                     if j == n_columns - 1:
  385.                         n_spaces = 0
  386.                     else:
  387.                         n_spaces = col_width - len(completions[ind])
  388.                     self.__insert(iter, completions[ind] + " " * n_spaces)
  389.             self.__insert(iter, "\n")
  390.  
  391.         self.__insert(iter, "%s%s%s" % (self.ps, line_start, line_end))
  392.         iter.set_line_offset(len(self.ps) + len(line_start))
  393.         self.__move_cursor_to(iter)
  394.         self.scroll_to_mark(self.cursor, 0.2)
  395.  
  396.     def __complete(self):
  397.         text = self.__get_text(self.__get_start(), self.__get_cursor())
  398.         start = ''
  399.         word = text
  400.         nonwords = self.nonword_re.findall(text)
  401.         if nonwords:
  402.             last = text.rfind(nonwords[-1]) + len(nonwords[-1])
  403.             start = text[:last]
  404.             word = text[last:]
  405.  
  406.         completions = self.complete(word)
  407.  
  408.         if completions:
  409.             prefix = _commonprefix(completions)
  410.             if prefix != word:
  411.                 start_iter = self.__get_start()
  412.                 start_iter.forward_chars(len(start))
  413.                 end_iter = start_iter.copy()
  414.                 end_iter.forward_chars(len(word))
  415.                 self.__delete(start_iter, end_iter)
  416.                 self.__insert(end_iter, prefix)
  417.             elif self.tab_pressed > 1:
  418.                 self.freeze_undo()
  419.                 self.__print_completions(completions)
  420.                 self.thaw_undo()
  421.                 self.tab_pressed = 0
  422.  
  423.     def complete(self, text):
  424.         return None
  425.  
  426.     def _get_line(self):
  427.         start = self.__get_start()
  428.         end = self.__get_end()
  429.         return self.buffer.get_text(start, end, False)
  430.  
  431.     def __replace_line(self, new_text):
  432.         start = self.__get_start()
  433.         end = self.__get_end()
  434.         self.__delete(start, end)
  435.         self.__insert(end, new_text)
  436.  
  437.     def _commit(self):
  438.         end = self.__get_cursor()
  439.         if not end.ends_line():
  440.             end.forward_to_line_end()
  441.         text = self._get_line()
  442.         self.__move_cursor_to(end)
  443.         self.freeze_undo()
  444.         self.__insert(end, "\n")
  445.         self.in_raw_input = False
  446.         self.history.commit(text)
  447.         self.do_raw_input(text)
  448.         self.thaw_undo()
  449.  
  450.     def do_raw_input(self, text):
  451.         pass
  452.  
  453.  
  454. class _Console(_ReadLine, code.InteractiveInterpreter):
  455.     def __init__(self, locals=None, banner=None,
  456.                  completer=None, use_rlcompleter=True,
  457.                  start_script=None, quit_func=None):
  458.         _ReadLine.__init__(self, quit_func)
  459.  
  460.         code.InteractiveInterpreter.__init__(self, locals)
  461.         self.locals["__console__"] = self
  462.  
  463.         self.start_script = start_script
  464.         self.completer = completer
  465.         self.banner = banner
  466.  
  467.         if not self.completer and use_rlcompleter:
  468.             try:
  469.                 import rlcompleter
  470.                 self.completer = rlcompleter.Completer()
  471.             except ImportError:
  472.                 pass
  473.  
  474.         self.ps1 = ">>> "
  475.         self.ps2 = "... "
  476.         self.__start()
  477.         self.run_on_raw_input = start_script
  478.         self.raw_input(self.ps1)
  479.  
  480.     def __start(self):
  481.         self.cmd_buffer = ""
  482.  
  483.         self.freeze_undo()
  484.         self.thaw_undo()
  485.  
  486.         self.do_delete = True
  487.         self.buffer.set_text("")
  488.         self.do_delete = False
  489.  
  490.         if self.banner:
  491.             iter = self.buffer.get_start_iter()
  492.             self.buffer.insert_with_tags_by_name(iter, self.banner, "stdout")
  493.             if not iter.starts_line():
  494.                 self.buffer.insert(iter, "\n")
  495.  
  496.     def clear(self, start_script=None):
  497.         if start_script is None:
  498.             start_script = self.start_script
  499.         else:
  500.             self.start_script = start_script
  501.  
  502.         self.__start()
  503.         self.run_on_raw_input = start_script
  504.  
  505.     def do_raw_input(self, text):
  506.         if self.cmd_buffer:
  507.             cmd = self.cmd_buffer + "\n" + text
  508.         else:
  509.             cmd = text
  510.  
  511.         saved_stdout, saved_stderr = sys.stdout, sys.stderr
  512.         sys.stdout, sys.stderr = self._stdout, self._stderr
  513.  
  514.         if self.runsource(cmd):
  515.             self.cmd_buffer = cmd
  516.             ps = self.ps2
  517.         else:
  518.             self.cmd_buffer = ''
  519.             ps = self.ps1
  520.  
  521.         sys.stdout, sys.stderr = saved_stdout, saved_stderr
  522.         self.raw_input(ps)
  523.  
  524.     def do_command(self, code):
  525.         try:
  526.             eval(code, self.locals)
  527.         except SystemExit:
  528.             raise
  529.         except:
  530.             self.showtraceback()
  531.  
  532.     def runcode(self, code):
  533.         if gtk.pygtk_version[1] < 8:
  534.             self.do_command(code)
  535.         else:
  536.             self.emit("command", code)
  537.  
  538.     def exec_command(self, command):
  539.         if self._get_line():
  540.             self._commit()
  541.         self.buffer.insert_at_cursor(command)
  542.         self._commit()
  543.  
  544.     def complete_attr(self, start, end):
  545.         try:
  546.             obj = eval(start, self.locals)
  547.             strings = dir(obj)
  548.  
  549.             if end:
  550.                 completions = {}
  551.                 for s in strings:
  552.                     if s.startswith(end):
  553.                         completions[s] = None
  554.                 completions = completions.keys()
  555.             else:
  556.                 completions = strings
  557.  
  558.             completions.sort()
  559.             return [start + "." + s for s in completions]
  560.         except:
  561.             return None
  562.  
  563.     def complete(self, text):
  564.         if self.completer:
  565.             completions = []
  566.             i = 0
  567.             try:
  568.                 while 1:
  569.                     s = self.completer.complete(text, i)
  570.                     if s:
  571.                         completions.append(s)
  572.                         i = i + 1
  573.                     else:
  574.                         completions.sort()
  575.                         return completions
  576.             except NameError:
  577.                 return None
  578.  
  579.         dot = text.rfind(".")
  580.         if dot >= 0:
  581.             return self.complete_attr(text[:dot], text[dot+1:])
  582.  
  583.         completions = {}
  584.         strings = keyword.kwlist
  585.  
  586.         if self.locals:
  587.             strings.extend(self.locals.keys())
  588.  
  589.         try: strings.extend(eval("globals()", self.locals).keys())
  590.         except: pass
  591.  
  592.         try:
  593.             exec "import __builtin__" in self.locals
  594.             strings.extend(eval("dir(__builtin__)", self.locals))
  595.         except:
  596.             pass
  597.  
  598.         for s in strings:
  599.             if s.startswith(text):
  600.                 completions[s] = None
  601.         completions = completions.keys()
  602.         completions.sort()
  603.         return completions
  604.  
  605.  
  606. def ReadLineType(t=gtk.TextView):
  607.     class readline(t, _ReadLine):
  608.         def __init__(self, *args, **kwargs):
  609.             t.__init__(self)
  610.             _ReadLine.__init__(self, *args, **kwargs)
  611.         def do_key_press_event(self, event):
  612.             return _ReadLine.do_key_press_event(self, event, t)
  613.     gobject.type_register(readline)
  614.     return readline
  615.  
  616. def ConsoleType(t=gtk.TextView):
  617.     class console_type(t, _Console):
  618.         __gsignals__ = {
  619.             'command' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (object,)),
  620.             'key-press-event' : 'override'
  621.           }
  622.  
  623.         def __init__(self, *args, **kwargs):
  624.             if gtk.pygtk_version[1] < 8:
  625.                 gobject.GObject.__init__(self)
  626.             else:
  627.                 t.__init__(self)
  628.             _Console.__init__(self, *args, **kwargs)
  629.  
  630.         def do_command(self, code):
  631.             return _Console.do_command(self, code)
  632.  
  633.         def do_key_press_event(self, event):
  634.             return _Console.do_key_press_event(self, event, t)
  635.  
  636.     if gtk.pygtk_version[1] < 8:
  637.         gobject.type_register(console_type)
  638.  
  639.     return console_type
  640.  
  641. ReadLine = ReadLineType()
  642. Console = ConsoleType()
  643.  
  644. def _make_window():
  645.     window = gtk.Window()
  646.     window.set_title("pyconsole.py")
  647.     swin = gtk.ScrolledWindow()
  648.     swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
  649.     window.add(swin)
  650.     console = Console(banner="Hello there!",
  651.                       use_rlcompleter=False,
  652.                       start_script="from gtk import *\n")
  653.     swin.add(console)
  654.     window.set_default_size(500, 400)
  655.     window.show_all()
  656.  
  657.     if not gtk.main_level():
  658.         window.connect("destroy", gtk.main_quit)
  659.         gtk.main()
  660.  
  661.     return console
  662.  
  663. if __name__ == '__main__':
  664.     if len(sys.argv) < 2 or sys.argv[1] != '-gimp':
  665.         _make_window()
  666.